<template>
  <div class="canvas f-g f-r">
    <div class="menu">
      <el-collapse v-model="activeNames">
        <el-collapse-item name="custom" title="自定义节点">
          <div class="content f-r f-w">
            <div
              :draggable="true"
              class="menu-item"
              @dragstart="
                onDrag($event, {
                  name: 'text',
                  text: '双击输入文本',
                  font: { color: '#000' },
                  rect: { width: 120, height: 50 },
                  data: { type: 'text' }
                })
              "
            >
              普通文本
            </div>
          </div>
        </el-collapse-item>
    
          <el-collapse-item v-for="(item, i) in Tools2" :key="i" :title="item.name" :name="item.stage">
              <div class="content f-r f-w">
                  <div
                      v-for="(sub, j) in (item.productVoList || []).filter(el => el.display)"
                      :key="j"
                      :draggable="true"
                      class="menu-item"
                      @dragstart="onDrag($event, sub)"
                  >
                      {{ sub.productName }}
                  </div>
              </div>
          </el-collapse-item>
          <el-collapse-item v-for="(item, i) in Tools" :key="i" :title="item.name" :name="item.stage">
              <div style="">(必经)</div>
              <div class="content">
                  <div
                      v-for="(sub, j) in (item.productVoList || []).filter(el => el.display&& el.process === 1)"
                      :key="j"
                      :draggable="true"
                      class="node-card f-r a-c j-b"
                      @dragstart="onDrag($event, sub)"
                  >
                      <div class="node-name f-g">{{ sub.productName }}</div>
                  </div>
              </div>
              <div class="">(可选)</div>
              <div class="content">
                  <div
                      v-for="(sub, j) in (item.productVoList || []).filter(el => el.display&& el.process === 2)"
                      :key="j"
                      :draggable="true"
                      class="node-card f-r a-c j-b"
                      @dragstart="onDrag($event, sub)"
                  >
                      <div class="node-name f-g">{{ sub.productName }}</div>
                  </div>
              </div>
          </el-collapse-item>
      </el-collapse>
    </div>
    <div class="body f-g">
      <div :id="domId" class="full" @contextmenu="onContextMenu($event)" />
    </div>
    <CanvasContextMenu
      v-show="contextmenu.left"
      :style="contextmenu"
      :context-menu-list="contextMenuList"
      @context="handleContext"
    />
  </div>
</template>
<script>
function createRandomId() {
  return (
    (Math.random() * 10000000).toString(16).substr(0, 4) +
    "-" +
    new Date().getTime() +
    "-" +
    Math.random()
      .toString()
      .substr(2, 5)
  );
}
import CanvasContextMenu from "./CanvasContextMenu";
import { Topology } from "@topology/core";
import { http_project_process, http_project_process_template } from "@/api";
// 配置项
const canvasOptions = {
  lineName: "line",
  minScale: 0,
  maxScale: 50,
  // 连线颜色
  font: {
    color: "#fff",
    fontSize: 12
  },
  // 键盘事件 如 删除 移动
  keydown: -1,
  // 缩放 如 ctrl + mousewheel 缩放
  disableScale: true,
  // 移动 如 ctrl + mouse 移动
  disableTranslate: true,
  disableEmptyLine: false,
  autoAnchor: false,
  // autoExpandDistance: 0,
  cacheLen: 0,
  anchorFillStyleL: "#1976d2",
  dockFillStyle: "#1976d2",
  hideInput: false
};
const stepMap = {
  1: "项目立项阶段",
  2: "规划许可阶段",
  3: "施工许可阶段",
  4: "竣工验收阶段"
};
export default {
  name: "Canvas",
  components: {
    CanvasContextMenu
  },
  data() {
    return {
      templateId: "",
      category: "",
      subCategory: "",
      activeNames: [],
      Tools2: [
      ],
      Tools: [],
      domId: createRandomId(),
      canvas: null,
      contextmenu: {
        left: null,
        top: null,
        bottom: null
      },
      nodeData: {
        data: {}
      },
      type: "",
      typeName: "",
      dialogId: ""
    };
  },
  computed: {
    contextMenuList() {
      return [
        {
          index: "delete",
          name: "删除",
          line: false
        }
      ];
    }
  },
  beforeDestroy() {
    /**
     *  销毁画布
     */
    this.canvas.destroy();
    this.canvas = null;
    document.onclick = null;
  },
  mounted() {
    this.initCanvas();
  },
  methods: {
    async initAdd(item) {
      try {
        const { bigCategoryId, smallCategoryId } = item;
        this.category = bigCategoryId;
        this.subCategory = smallCategoryId;
        // 节点 解析节点
        const nodeRes = await http_project_process_template.getNodesByCategory({
          bigCategoryId,
          smallCategoryId,
          isMatter: 2
        });
        this.Tools = nodeRes.data.filter(el => el.stage < 5).map(el => {
          return {
            name: stepMap[el.stage],
            ...el,
            productVoList: el.productVoList.map(el2 => {
              return {
                display: true,
                text: el2.productName,
                rect: {
                  width: 220,
                  height: 60
                },
                name: "rectangle",
                data: {
                  type: "node",
                  ...el2
                },
                ...el2
              };
            })
          };
        });
          this.Tools2 = nodeRes.data.filter(el => el.stage === 5).map(el => {
              return {
                  name: '标',
                  ...el,
                  productVoList: el.productVoList.map(el2 => {
                      return {
                          display: true,
                          text: el2.productName,
                          rect: { width: 50, height: 50 },
                          name: 'circle',
                          data: {
                              type: 'node',
                              ...el2
                          },
                          ...el2
                      }
                  })
              }
          })
    
          // 模版详情 存在打开canvas
        const templateRes = await http_project_process_template.read({
          bigCategoryId,
          smallCategoryId
        });
        this.templateId = templateRes.data.mainTemplateId;
        const { canvas, productList } = templateRes.data;
        this.Tools.forEach(el => {
          el.productVoList.forEach(el2 => {
            if (productList.find(p => p.productCode === el2.productCode)) {
              el2.display = false;
            }
          });
        });
          this.Tools2.forEach(el => {
              el.productVoList.forEach(el2 => {
                  if (productList.find(p => p.productCode === el2.productCode)) {
                      el2.display = false;
                  }
              });
          });
        if (!canvas) {
          this.canvas.open();
          setTimeout(() => {
            this.canvas.canvasPos = this.canvas.divLayer.canvas.getBoundingClientRect();
          });
          return;
        }
        if (typeof canvas !== "string") {
          this.canvas.open();
          setTimeout(() => {
            this.canvas.canvasPos = this.canvas.divLayer.canvas.getBoundingClientRect();
          });
          return;
        }
        if (!canvas.includes("pens")) {
          this.canvas.open();
          setTimeout(() => {
            this.canvas.canvasPos = this.canvas.divLayer.canvas.getBoundingClientRect();
          });
          return;
        }
        // 打开画布
        this.canvas.open(canvas);
        this.setText(productList)
        setTimeout(() => {
          this.canvas.canvasPos = this.canvas.divLayer.canvas.getBoundingClientRect();
          this.canvas.overflow()
          this.canvas.render()
        });
      } catch {
        this.canvas.open();
      }
    },
    async initEdit({ item, templateRes }) {
      try {
        const { bigCategoryId, smallCategoryId } = item;
        this.category = bigCategoryId;
        this.subCategory = smallCategoryId;
        // 节点 解析节点
        const nodeRes = await http_project_process_template.getNodesByCategory({
          bigCategoryId,
          smallCategoryId,
          isMatter: 2
        });
          this.Tools = nodeRes.data.filter(el => el.stage < 5).map(el => {
              return {
                  name: stepMap[el.stage],
                  ...el,
                  productVoList: el.productVoList.map(el2 => {
                      return {
                          display: true,
                          text: el2.productName,
                          rect: {
                              width: 220,
                              height: 60
                          },
                          name: "rectangle",
                          data: {
                              type: "node",
                              ...el2
                          },
                          ...el2
                      };
                  })
              };
          });
          this.Tools2 = nodeRes.data.filter(el => el.stage === 5).map(el => {
              return {
                  name: '标',
                  ...el,
                  productVoList: el.productVoList.map(el2 => {
                      return {
                          display: true,
                          text: el2.productName,
                          rect: { width: 50, height: 50 },
                          name: 'circle',
                          data: {
                              type: 'node',
                              ...el2
                          },
                          ...el2
                      }
                  })
              }
          })
        this.templateId = templateRes.data.mainTemplateId;
        const { canvas, productList } = templateRes.data;
        this.Tools.forEach(el => {
          el.productVoList.forEach(el2 => {
            if (productList.find(p => p.productCode === el2.productCode)) {
              el2.display = false;
            }
          });
        });
          this.Tools2.forEach(el => {
              el.productVoList.forEach(el2 => {
                  if (productList.find(p => p.productCode === el2.productCode)) {
                      el2.display = false;
                  }
              });
          });
        if (!canvas) {
          this.canvas.open();
          setTimeout(() => {
            this.canvas.canvasPos = this.canvas.divLayer.canvas.getBoundingClientRect();
          });
          return;
        }
        if (typeof canvas !== "string") {
          this.canvas.open();
          setTimeout(() => {
            this.canvas.canvasPos = this.canvas.divLayer.canvas.getBoundingClientRect();
          });
          return;
        }
        if (!canvas.includes("pens")) {
          this.canvas.open();
          setTimeout(() => {
            this.canvas.canvasPos = this.canvas.divLayer.canvas.getBoundingClientRect();
          });
          return;
        }
        // 打开画布
        this.canvas.open(canvas);
        this.setText(productList)
        setTimeout(() => {
          this.canvas.canvasPos = this.canvas.divLayer.canvas.getBoundingClientRect();
          this.canvas.overflow()
          this.canvas.render()
        });
      } catch {
        this.canvas.open();
        setTimeout(() => {
          this.canvas.canvasPos = this.canvas.divLayer.canvas.getBoundingClientRect();
        });
      }
    },
    setText(productList) {
      this.canvas.data.pens.forEach(pen => {
        if (pen.data) {
          if (pen.data.type === 'node') {
            const find = productList.find(
              p => p.productCode === pen.data.productCode
            )
            if (find) {
              pen.font.textAlign = 'left'
              pen.text = find.productName + '\n' + '开始时间：' + (find.startTime || '') + '\n' + '结束时间：' + (find.endTime || '')
            }
          }
        }
      })
    },
    /**
     *  初始化画布
     */
    initCanvas() {
      this.canvas = null;
      canvasOptions.on = this.onMessage;
      this.canvas = new Topology(this.domId, canvasOptions);
      setTimeout(() => {
        // 修复鼠标框选错位
        this.canvas.data.lineName = "polyline";
        this.canvas.data.toArrow = "";
      }, 1000);
    },
    onMessage(event, data) {
      if (event === "addNode") {
        if (data.name === "text") {
          data.font.color = "#000";
        }
        if (data && data.data && data.data.type === "node") {
          this.Tools.forEach(el => {
            el.productVoList.forEach(el2 => {
              if (el2.productCode === data.data.productCode) {
                el2.display = false;
              }
            });
          });
          this.Tools2.forEach(el => {
            el.productVoList.forEach(el2 => {
              if (el2.productCode === data.data.productCode) {
                el2.display = false;
              }
            });
          });
        }
      }
      if (event === "addLine") {
        data.strokeStyle = "#4880FF";
      }
      if (event === "delete") {
        const nodeData = data[0] || {};
        if (
          nodeData &&
          nodeData.type === 0 &&
          nodeData.data &&
          nodeData.data.type === "node"
        ) {
          this.Tools.forEach(el => {
            el.productVoList.forEach(el2 => {
              if (el2.productCode === nodeData.data.productCode) {
                el2.display = true;
              }
            });
          });
          this.Tools2.forEach(el => {
            el.productVoList.forEach(el2 => {
              if (el2.productCode === nodeData.data.productCode) {
                el2.display = true;
              }
            });
          });
        }
      }
    },
    onDrag(event, node) {
      event.dataTransfer.setData(
        "Topology",
        JSON.stringify({
          name: node.name,
          text: node.text,
          rect: node.rect,
          data: node.data,
          fillStyle: "#4880FF",
          paddingLeft: 20,
          paddingRight: 20,
          paddingTop: 5,
          paddingBottom: 5,
          font: {
            color: "#fff"
          }
        })
      );
    },
    /**
     *  右击事件
     */
    onContextMenu(event) {
      event.preventDefault();
      event.stopPropagation();
      if (event.clientY + 360 < document.body.clientHeight) {
        this.contextmenu = {
          left: event.clientX + "px",
          top: event.clientY + "px"
        };
      } else {
        this.contextmenu = {
          left: event.clientX + "px",
          bottom: document.body.clientHeight - event.clientY + "px"
        };
      }
    },
    /**
     *  处理右击选择
     */
    handleContext() {
      this.canvas.delete();
      this.contextmenu = {
        left: null,
        top: null,
        bottom: null
      };
    },
    save() {
      const productVoList = [];
      this.Tools.forEach(el => {
        el.productVoList.forEach(el2 => {
          if (!el2.display) {
            productVoList.push({
              productName: el2.productName,
              productCode: el2.productCode,
              isBidding: el2.isBidding,
              stage: el2.stage,
              process: el2.process
            });
          }
        });
      });
      http_project_process
        .updateCanvas({
          bigCategoryId: this.category,
          smallCategoryId: this.subCategory,
          projectId: this.$route.query.id,
          canvas: JSON.stringify(this.canvas.data),
          productVoList
        })
        .then(res => {
          this.$message.success(res.msg);
        });
    },
  }
};
</script>

<style scoped lang="scss">
.canvas {
  min-height: 600px;
  display: flex;
  background-color: #f2f2f2;
  padding: 10px;
  overflow: hidden;
  .menu {
    width: 300px;
    height: 100%;
    background-color: #fff;
    padding-left: 20px;
    overflow: auto;
    .item {
      width: 100%;
      .item-header {
        height: 40px;
        padding-left: 10px;
        line-height: 40px;
        border-bottom: 1px solid #666;
      }
    }
    .content {
      padding: 10px 20px 10px 0;
    }
    .icon-list {
      width: 100%;
      display: flex;
      flex-wrap: wrap;
      .icon-item {
        margin-right: 5px;
        &:hover {
          border: 1px solid #e2e2e2;
          border-radius: 3px;
        }
        cursor: pointer;
        width: 30%;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        img {
          width: 100%;
        }
      }
    }
  }
  .body {
    margin-left: 20px;
    position: relative;
    background-color: #ffffff;
    .canvas-header {
      position: absolute;
      right: 10px;
      top: 10px;
      z-index: 99;
    }
    .full {
      width: 100%;
      height: 100%;
      touch-action: none;
    }
  }
}
.menu-item {
  width: 60px;
  height: 60px;
  background-color: #4880ff;
  text-align: center;
  line-height: 60px;
  color: #ffffff;
  border-radius: 50%;
  cursor: pointer;
  margin-right: 10px;
  margin-bottom: 10px;
}
.node-card {
  cursor: pointer;
  width: 100%;
  height: 68px;
  background: #4880ff;
  border-radius: 8px 8px 8px 8px;
  opacity: 1;
  padding: 10px;
  margin-bottom: 13px;
  .node-name {
    user-select: none;
    font-size: 14px;
    line-height: 16px;
    text-align: center;
    padding-right: 10px;
    color: #ffffff;
  }
  .node-btn {
    height: 100%;
    i {
      color: #ffffff;
      font-size: 18px;
      cursor: pointer;
    }
  }
}
</style>
